package dao

import (
	"context"
	"prod/internal/model"
)

func (d *Dao) GetMenus(ctx context.Context, sgId uint32) (views []*model.MenuQueryModel, err error) {
	if err = d.TransContext(ctx).Model(&model.Menu{}).Select(
		"id, name, pic, can_modify_price, count(distinct prod_id) as prod_count,"+
			"array_to_string(array_agg(store_id),',') as store_ids").Joins(
		"LEFT OUTER JOIN pd_menu_prod ON id = pd_menu_prod.menu_id AND pd_menu_prod.status=true").Joins(
		"LEFT OUTER JOIN pd_menu_store ON id = pd_menu_store.menu_id AND pd_menu_store.status=true").Where(
		"pd_menu.sg_id = ? AND pd_menu.status = true",
		sgId).Group("pd_menu.id").Order(
		"pd_menu.id asc").Scan(&views).Error; err != nil {
		err = d.processSqlError(err)
		return
	}
	return
}

func (d *Dao) GetMenuInfo(ctx context.Context, menuId, sgId uint32) (view *model.MenuQueryModel, err error) {
	view = &model.MenuQueryModel{}
	if err = d.TransContext(ctx).Model(&model.Menu{}).Select(
		"id, name, pic, can_modify_price, count(distinct prod_id) as prod_count,"+
			"array_to_string(array_agg(store_id),',') as store_ids").Joins(
		"LEFT OUTER JOIN pd_menu_prod ON id = pd_menu_prod.menu_id AND pd_menu_prod.status=true").Joins(
		"LEFT OUTER JOIN pd_menu_store ON id = pd_menu_store.menu_id AND pd_menu_store.status=true").Where(
		"pd_menu.id = ? AND pd_menu.sg_id = ? AND pd_menu.status = true",
		menuId, sgId).Group("pd_menu.id").Take(view).Error; err != nil {
		err = d.processSqlError(err)
		return
	}
	return
}

func (d *Dao) GetMenuById(ctx context.Context, menuId, sgId uint32) (
	menu *model.Menu, err error) {
	menu = &model.Menu{}
	if err = d.TransContext(ctx).Take(menu,
		"id = ? AND sg_id = ? AND status = ?",
		menuId, sgId, true).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuByName(ctx context.Context, name string, sgId uint32) (
	menu *model.Menu, err error) {
	menu = &model.Menu{}
	if err = d.TransContext(ctx).Take(menu,
		"sg_id = ? AND name = ? AND status = ?",
		sgId, name, true).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuStore(ctx context.Context, storeId uint32) (
	menuStore *model.MenuStore, err error) {
	menuStore = &model.MenuStore{}
	if err = d.TransContext(ctx).Model(&model.MenuStore{}).Where(
		"store_id = ? AND status = ?",
		storeId, true).Take(menuStore).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuStores(ctx context.Context, menuId uint32) (
	menuStores []*model.MenuStore, err error) {
	if err = d.TransContext(ctx).Model(&model.MenuStore{}).Where(
		"menu_id = ? AND status = ?",
		menuId, true).Scan(&menuStores).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuStoresByStoreIds(ctx context.Context, storeIds []uint32) (
	menuStores []*model.MenuStore, err error) {
	if err = d.TransContext(ctx).Model(&model.MenuStore{}).Where(
		"store_id in ? AND status = ?",
		storeIds, true).Scan(&menuStores).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuProds(ctx context.Context, menuId uint32) (
	menuProds []*model.MenuProd, err error) {
	if err = d.TransContext(ctx).Model(&model.MenuProd{}).Where(
		"menu_id = ? AND status = ? ",
		menuId, true).Scan(&menuProds).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuProdsByProdIds(ctx context.Context, menuId uint32, prodIds []uint64) (
	menuProds []*model.MenuProd, err error) {
	if err = d.TransContext(ctx).Model(&model.MenuProd{}).Where(
		"menu_id = ? AND prod_id in ? AND status = ? ",
		menuId, prodIds, true).Scan(&menuProds).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) CheckProdsExistsInMenu(ctx context.Context, prodIds []uint64) (
	err error) {
	if err = d.TransContext(ctx).Model(&model.MenuProd{}).Where(
		"prod_id in ? AND status = ? ",
		prodIds, true).Take(&model.MenuProd{}).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) CheckMenuProdsExists(ctx context.Context, menuId uint32, prodIds []uint64) (
	err error) {
	if err = d.TransContext(ctx).Model(&model.MenuProd{}).Where(
		"menu_id = ? AND prod_id in ? AND status = ? ",
		menuId, prodIds, true).Take(&model.MenuProd{}).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuSkuInfoByProdIds(ctx context.Context, menuId uint32, prodIds []uint64) (
	menuSkus []*model.MenuSkuQueryModel, err error) {
	if len(prodIds) == 0 {
		return
	}
	if err = d.TransContext(ctx).Model(&model.Sku{}).Select(
		"pd_sku.prod_id, id, items, pd_sku.price as sku_price, pd_menu_sku.price as menu_price, weight").Joins(
		"LEFT OUTER JOIN pd_menu_sku ON menu_id = ? AND pd_menu_sku.prod_id in ? "+
			"AND sku_id=id AND pd_menu_sku.status = ?", menuId, prodIds, true).Where(
		"pd_sku.prod_id in ? AND pd_sku.status=?",
		prodIds, true).Scan(&menuSkus).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) GetMenuProdsByCondition(ctx context.Context, menuId, prodTypeId, sgId, pStoreId,
	pageNo, pageSize uint32, query string, excludedProdIds []uint64) (
	prods []*model.Product, total uint32, err error) {
	db := d.TransContext(ctx).Model(&model.Product{}).Joins(
		"JOIN pd_menu_prod ON menu_id = ? and prod_id=id AND pd_menu_prod.status = ?",
		menuId, true).Where(
		"pd_product.sg_id = ? AND p_store_id = ? AND pd_product.status = ?",
		sgId, pStoreId, true)
	if prodTypeId != 0 {
		var queryTypeIds []uint32
		if queryTypeIds, err = d.getQueryTypeIds(ctx, prodTypeId, sgId, pStoreId); err != nil {
			return
		}
		if len(queryTypeIds) != 0 {
			db = db.Where("type_id in ?", queryTypeIds)
		} else {
			return
		}
	}
	if query != "" {
		db = db.Where("name like ", "%"+query+"%")
	}
	if len(excludedProdIds) != 0 {
		db = db.Where("id not in %s", excludedProdIds)
	}
	var rawTotal int64
	if err = db.Count(&rawTotal).Error; err != nil {
		err = d.processSqlError(err)
		return
	}
	total = uint32(rawTotal)
	if err = db.Offset(int((pageNo - 1) * pageSize)).Limit(
		int(pageSize)).Find(&prods).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}

func (d *Dao) DeleteMenuProdByIds(ctx context.Context, menuId uint32, prodIds []uint64,
	operator uint32) (err error) {
	if err = d.TransContext(ctx).Model(&model.MenuSku{}).Where(
		"menu_id = ? AND prod_id in ? AND status= ? ",
		menuId, prodIds, true).Updates(map[string]interface{}{
		"status":   false,
		"operator": operator,
	}).Error; err != nil {
		err = d.processSqlError(err)
	}
	if err = d.TransContext(ctx).Model(&model.MenuProd{}).Where(
		"menu_id = ? AND prod_id in ? AND status= ? ",
		menuId, prodIds, true).Updates(map[string]interface{}{
		"status":   false,
		"operator": operator,
	}).Error; err != nil {
		err = d.processSqlError(err)
	}
	return
}
